package sapling.main.view;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;

import net.miginfocom.swing.MigLayout;
import sapling.logic.algorithm.pcb.queue.FCFSQueue;
import sapling.logic.object.pcb.ProcessControlBlock;
import sapling.logic.object.pcb.attr.Priority;
import sapling.main.OSEnvironment;
import sapling.util.MyStrings;
import sapling.util.ReadConfig;

public class ApplicationMain extends JFrame {
	private OSEnvironment os;
	private Timer timer;
	private TimerTask task;
	private int[] priority = {Priority.NO_LEVEL, Priority.LEVEL_1, Priority.LEVEL_2,
			Priority.LEVEL_3, Priority.LEVEL_4, Priority.LEVEL_5, Priority.LEVEL_6,
			Priority.LEVEL_7, Priority.LEVEL_8, Priority.LEVEL_9};
	private String[] dispatches = {MyStrings.FCFS, MyStrings.PRIORITY, MyStrings.TSR};

	private JTable tProcReady;
	private MyTableModel tmProcReady;
	private JTextField tfProcRunning;
	private JTextField tfProcTag;
	private JComboBox cbPriority;
	private JComboBox cbDispatcher;
	private JSpinner spSlice;
	private JButton btRestart;
	private JButton btNew;
	private JSpinner spSliceNum;
	private JSpinner spLive;
	private JTextArea taLog;

	private boolean isAdded = false;

	public ApplicationMain() {

		this.os = OSEnvironment.getInstance();
		this.timer = new Timer();
		this.task = new TimerTask() {

			@Override
			public void run() {
				if (null == os.getPcbRunning()) {
					return;
				}
				os.change();
				refresh();
			}
		};

		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		JMenu mProc = new JMenu("进程");
		menuBar.add(mProc);

		JMenuItem miNew = new JMenuItem("新建");
		mProc.add(miNew);

		JMenuItem miSetting = new JMenuItem("设置");
		mProc.add(miSetting);

		JSeparator separator = new JSeparator();
		mProc.add(separator);

		JMenuItem mtExit = new JMenuItem("退出");
		mProc.add(mtExit);

		JMenu mHelp = new JMenu("帮助");
		menuBar.add(mHelp);

		JMenuItem miAbout = new JMenuItem("关于");
		mHelp.add(miAbout);
		getContentPane().setLayout(new MigLayout("", "[505.00,grow][91.00,grow]", "[grow]"));

		JPanel panel = new JPanel();
		getContentPane().add(panel, "cell 0 0,grow");
		panel.setLayout(new MigLayout("", "[497.00,grow]", "[][grow]"));

		tfProcRunning = new JTextField();
		panel.add(tfProcRunning, "cell 0 0,grow");
		tfProcRunning.setColumns(10);

		tmProcReady = new MyTableModel();

		JScrollPane scrollPane_1 = new JScrollPane();
		panel.add(scrollPane_1, "cell 0 1,grow");
		tProcReady = new JTable();
		scrollPane_1.setViewportView(tProcReady);
		tProcReady.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		tProcReady.setModel(tmProcReady);
		tProcReady.getColumnModel().getColumn(0).setResizable(false);
		tProcReady.getColumnModel().getColumn(1).setResizable(false);
		tProcReady.getColumnModel().getColumn(2).setResizable(false);
		tProcReady.getColumnModel().getColumn(3).setResizable(false);
		tProcReady.setRowHeight(25);

		JPanel panel_1 = new JPanel();
		getContentPane().add(panel_1, "cell 1 0,grow");
		panel_1.setLayout(new MigLayout("", "[11.00,grow]", "[][][][][18.00][grow]"));

		JPanel panel_2 = new JPanel();
		panel_1.add(panel_2, "cell 0 0,grow");
		panel_2.setLayout(new MigLayout("", "[11.00,grow][123.00,grow]", "[][][][]"));

		JLabel label = new JLabel("进程名：");
		panel_2.add(label, "cell 0 0,alignx trailing");

		tfProcTag = new JTextField();
		panel_2.add(tfProcTag, "cell 1 0,growx");
		tfProcTag.setColumns(10);

		JLabel label_1 = new JLabel("生存时长：");
		panel_2.add(label_1, "cell 0 1,alignx trailing");

		spLive = new JSpinner();
		spLive.setModel(new SpinnerNumberModel(10, 10, 500, 10));
		panel_2.add(spLive, "flowx,cell 1 1,growx");

		JLabel label_2 = new JLabel("优先级：");
		panel_2.add(label_2, "cell 0 2,alignx trailing");

		cbPriority = new JComboBox();
		cbPriority.setModel(new DefaultComboBoxModel(MyStrings.PRIORITY_STR));
		cbPriority.setSelectedIndex(MyStrings.PRIORITY.equals(ReadConfig.DISPATCHER) ? 5 : 0);
		cbPriority.setEnabled(MyStrings.PRIORITY.equals(ReadConfig.DISPATCHER));
		panel_2.add(cbPriority, "cell 1 2,growx");

		btNew = new JButton("新建进程");
		btNew.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (MyStrings.PRIORITY.equals(ReadConfig.DISPATCHER) && cbPriority.getSelectedIndex() == 0)
					return;
				os.create(tfProcTag.getText(), (int) spLive.getModel().getValue(),
						priority[cbPriority.getSelectedIndex()]);
				isAdded = true;
				refresh();
			}
		});
		panel_2.add(btNew, "cell 1 3,alignx right");

		JLabel label_7 = new JLabel("个时间片");
		panel_2.add(label_7, "cell 1 1");

		JSeparator separator_1 = new JSeparator();
		panel_1.add(separator_1, "cell 0 1");

		JPanel panel_3 = new JPanel();
		panel_1.add(panel_3, "cell 0 2,grow");
		panel_3.setLayout(new MigLayout("", "[11.00,grow][123.00,grow]", "[][][][27.00]"));

		JLabel label_3 = new JLabel("调度方法：");
		panel_3.add(label_3, "cell 0 0,alignx trailing");

		String temp = ReadConfig.DISPATCHER;
		cbDispatcher = new JComboBox();
		cbDispatcher.setModel(new DefaultComboBoxModel(dispatches));
		cbDispatcher.setSelectedIndex(MyStrings.FCFS.equals(temp) ? 0 : (MyStrings.PRIORITY.equals(temp) ? 1 : 2));
		panel_3.add(cbDispatcher, "cell 1 0,growx");

		JLabel label_4 = new JLabel("时间片长：");
		panel_3.add(label_4, "cell 0 1,alignx right");

		spSlice = new JSpinner();
		spSlice.setModel(new SpinnerNumberModel(ReadConfig.SLICE, 10, 5000, 100));
		panel_3.add(spSlice, "flowx,cell 1 1,growx");

		JLabel label_5 = new JLabel("轮转：");
		panel_3.add(label_5, "cell 0 2,alignx right");

		spSliceNum = new JSpinner();
		spSliceNum.setModel(new SpinnerNumberModel(ReadConfig.SLICE_NUM, 1, 20, 1));
		panel_3.add(spSliceNum, "flowx,cell 1 2,growx");

		btRestart = new JButton("重启系统");
		btRestart.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				ReadConfig.update("dispatcher", dispatches[cbDispatcher.getSelectedIndex()]);
				ReadConfig.update("timeSlice", "" + spSlice.getModel().getValue());
				ReadConfig.update("sliceNum", "" + spSliceNum.getModel().getValue());
				ReadConfig.store();
				os.restart();
				cbPriority.setSelectedIndex(MyStrings.PRIORITY.equals(ReadConfig.DISPATCHER) ? 5 : 0);
				cbPriority.setEnabled(MyStrings.PRIORITY.equals(ReadConfig.DISPATCHER));
				isAdded = true;
				refresh();
			}
		});
		panel_3.add(btRestart, "cell 1 3,alignx right");

		JLabel label_6 = new JLabel("个时间片");
		panel_3.add(label_6, "cell 1 2");

		JLabel lblMs = new JLabel("ms");
		panel_3.add(lblMs, "cell 1 1");

		JSeparator separator_2 = new JSeparator();
		panel_1.add(separator_2, "cell 0 3");

		JLabel label_8 = new JLabel("日志信息：");
		panel_1.add(label_8, "cell 0 4,aligny bottom");

		JScrollPane scrollPane = new JScrollPane();
		panel_1.add(scrollPane, "cell 0 5,grow");

		taLog = new JTextArea();
		scrollPane.setViewportView(taLog);


		timer.schedule(task, 0, ReadConfig.SLICE*ReadConfig.SLICE_NUM);
		// timer.scheduleAtFixedRate(task, 0, 1000);
	}

	private void refresh() {
		tfProcRunning.setText(this.os.getPcbRunning() == null ? "" : this.os.getPcbRunning().toString());
		if (this.os.getPcbQueue() instanceof FCFSQueue && !this.isAdded &&
				this.os.getPcbRunning()!=null &&
				this.os.getPcbRunning().getLiveLong()!=this.os.getPcbRunning().getInitLiveLong()) {
			return;
		}
		tmProcReady.removeAll();
		ProcessControlBlock[] temp = this.os.getPcbQueue().toArray();
		for (int i = 0; i < temp.length; i++) {
			tmProcReady.addRow(new Object[]{
					temp[i].getTag(), temp[i].getId(), temp[i].getLiveLong(), MyStrings.PRIORITY_STR[temp[i].getPriority()]
			});
		}
		this.isAdded = false;
	}

	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
				| UnsupportedLookAndFeelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				ApplicationMain w = new ApplicationMain();
				w.setSize(770, 550);
				w.setLocationRelativeTo(w.getOwner());
				w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				w.setVisible(true);
			}
		});

	}

	private class MyTableModel extends DefaultTableModel {
		MyTableModel() {
			super(new Object[][]{},
					new String[]{"\u8FDB\u7A0B\u540D", "PID", "\u65F6\u957F", "\u4F18\u5148\u7EA7"});

		}

		Class[] columnTypes = new Class[]{String.class, String.class, String.class, String.class};

		public Class getColumnClass(int columnIndex) {
			return columnTypes[columnIndex];
		}

		boolean[] columnEditables = new boolean[]{false, false, false, false};

		public boolean isCellEditable(int row, int column) {
			return columnEditables[column];
		}

		public void removeAll() {
			int length = this.getRowCount();
			for (int i = length; i > 0; i--) {
				this.removeRow(i - 1);
			}
		}
	}
}
